let _vue = null;

export default class Router {
  $options = null;
  routeMap = null;
  data = null;
  // Vue.use 方法会调用对应组件的 install 方法
  static install(Vue) {
    // 1. 判断插件是否被安装
    if (Router.install.installed) {
      return;
    }
    Router.install.installed = true;
    // 2. 将`install`方法中的参数`vue`插入到全局中
    _vue = Vue;
    // 3. 将创建`vue`实例时候传入的`Router`对象注入到`vue`实例上
    // 使用混入
    _vue.mixin({
      beforeCreate() {
        if (this.$options.router) {
          _vue.prototype.$router = this.$options.router;
          this.$options.router.init();
        }
      },
    });
  }

  constructor(options) {
    // 记录构造函数中传入的选项
    this.options = options;
    // 将来将options的规则解析到 routeMap中来，键值对的形式
    this.routeMap = {};
    // data是响应式的对象，使用vue的提供的方法,方便之后路由更新我们可以及时更新页面
    this.data = _vue.observable({
      current: "/",
    });
  }
  /**
   * @description 注册初始化方法
   */
  init() {
    this.createRouteMap();
    this.initComponents(_vue);
    this.initEvent();
  }
  /**
   * @description  遍历路由规则,把路由规则解析成键值对的形式，储存到routeMap中
   */
  createRouteMap() {
    this.options.routes.forEach((route) => {
      this.routeMap[route.path] = route.component;
    });
  }
  /**
   *
   * @param {*} vue 的实例
   */
  initComponents(vue) {
    const self = this;
    vue.component("router-link", {
      props: {
        to: String,
      },
      // template: '<a :href="to"><slot></slot></a>',
      render(h) {
        return h(
          "a",
          {
            attrs: {
              href: "#" + this.to,
            },
            on: {
              click: this.clickHander,
            },
          },
          [this.$slots.default]
        );
      },
      methods: {
        clickHander(e) {
          history.pushState({}, "#", this.to);
          this.$router.data.current = "#" + this.to;
          e.preventDefault();
        },
      },
    });
    vue.component("router-view", {
      render(h) {
        // 我们需要先找到当前的路由地址 self.data.current
        // 找到对应路由所对应的组件
        const component = self.routeMap[self.data.current];
        // h函数可以将我们的路由转换成虚拟dom传递给页面
        return h(component);
      },
    });
  }
  initEvent() {
    window.addEventListener("hashchange", this.onHashChange.bind(this));
    window.addEventListener("load", this.onHashChange.bind(this));
  }
  onHashChange() {
    //当路由地址发生变化，重新记录当前的路径
    this.data.current = window.location.hash.substr(1) || "/";
  }
}
